﻿//"The contents of this file are subject to the Mozilla Public License
//Version 1.1 (the "License"); you may not use this file except in
//compliance with the License. You may obtain a copy of the License at
//http://www.mozilla.org/MPL/

//Software distributed under the License is distributed on an "AS IS"
//basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//License for the specific language governing rights and limitations
//under the License.

//The Original Code is TSharp.

//The Initial Developer of the Original Code is Mar3ek (http://mar3ek.wordpress.com).
//Portions created by Mar3ek are Copyright (C) 2010
//Mar3ek (http://mar3ek.wordpress.com). All Rights Reserved.

//Contributor(s): ______________________________________.

//Alternatively, the contents of this file may be used under the terms
//of the _____ license (the  "[___] License"), in which case the
//provisions of [______] License are applicable instead of those
//above.  If you wish to allow use of your version of this file only
//under the terms of the [____] License and not to allow others to use
//your version of this file under the MPL, indicate your decision by
//deleting  the provisions above and replace  them with the notice and
//other provisions required by the [___] License.  If you do not delete
//the provisions above, a recipient may use your version of this file
//under either the MPL or the [___] License."

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;

namespace TSharp
{
    public partial class Twitter
    {
        #region List members

        #region GetListMembers

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>List of users</returns>
        public Collection<TwitterUser> GetListMembers(string screenName, string listSlug)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");

            var result = SendRequest(RequestMethod.Get,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listSlug),
                                        true);

            var doc = XDocument.Parse(result);
            var usersList = doc.Element("users_list");

            var twitterUsers = new Collection<TwitterUser>();
            // ReSharper disable PossibleNullReferenceException
            if (usersList != null)
                twitterUsers = new Collection<TwitterUser>(usersList.Element("users").Elements("user").Select(ParseAuthor).ToList());
            // ReSharper restore PossibleNullReferenceException
            return twitterUsers;
        }

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>List of users</returns>
        public Collection<TwitterUser> GetListMembers(string screenName, ulong listId)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");

            var result = SendRequest(RequestMethod.Get,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listId),
                                        true);

            var doc = XDocument.Parse(result);
            var usersList = doc.Element("users_list");

            var twitterUsers = new Collection<TwitterUser>();
            if (usersList != null)
                // ReSharper disable PossibleNullReferenceException
                twitterUsers = new Collection<TwitterUser>(usersList.Element("users").Elements("user").Select(ParseAuthor).ToList());
            // ReSharper restore PossibleNullReferenceException
            return twitterUsers;
        }

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="user">The owner of the list</param>
        /// <param name="list">The target list</param>
        /// <returns>List of users</returns>
        /// <exception cref="ArgumentNullException"><paramref name="user"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list"/> is <c>null</c>.</exception>
        public Collection<TwitterUser> GetListMembers(TwitterUser user, TwitterList list)
        {
            if (user == null) throw new ArgumentNullException("user");
            if (list == null) throw new ArgumentNullException("list");

            return GetListMembers(user.ScreenName, list.Id);
        }

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="cursor">Breaks the results into pages. This is recommended for users who are following many users. Provide a value of -1 to begin paging</param>
        /// <param name="previousCursor">Start index of the previous page</param>
        /// <param name="nextCursor">Start index of the next page</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>List of users</returns>
        public Collection<TwitterUser> GetListMembers(string screenName, string listSlug, long cursor, out long previousCursor,
                                                out long nextCursor)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");

            var result = SendRequest(RequestMethod.Get,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listSlug),
                                        true,
                                        new KeyValuePair<string, string>("cursor", cursor.ToString()));

            var doc = XDocument.Parse(result);
            var usersList = doc.Element("users_list");

            var users = new Collection<TwitterUser>();
            previousCursor = 0;
            nextCursor = 0;
            if (usersList != null)
            {
                // ReSharper disable PossibleNullReferenceException
                users = new Collection<TwitterUser>(usersList.Element("users").Elements("user").Select(ParseAuthor).ToList());

                nextCursor = long.Parse(usersList.Element("next_cursor").Value);
                previousCursor = long.Parse(usersList.Element("previous_cursor").Value);
                // ReSharper restore PossibleNullReferenceException
            }

            return users;
        }

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The slug of the target list</param>
        /// <param name="cursor">Breaks the results into pages. This is recommended for users who are following many users. Provide a value of -1 to begin paging</param>
        /// <param name="previousCursor">Start index of the previous page</param>
        /// <param name="nextCursor">Start index of the next page</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>List of users</returns>
        public Collection<TwitterUser> GetListMembers(string screenName, ulong listId, long cursor, out long previousCursor,
                                                out long nextCursor)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("screenName");
            if (cursor < -1) throw new ArgumentOutOfRangeException("cursor");

            var result = SendRequest(RequestMethod.Get,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listId),
                                        true,
                                        new KeyValuePair<string, string>("cursor", cursor.ToString()));

            var doc = XDocument.Parse(result);
            var usersList = doc.Element("users_list");

            var users = new Collection<TwitterUser>();
            previousCursor = 0;
            nextCursor = 0;
            if (usersList != null)
            {
                // ReSharper disable PossibleNullReferenceException
                users = new Collection<TwitterUser>(usersList.Element("users").Elements("user").Select(ParseAuthor).ToList());

                nextCursor = long.Parse(usersList.Element("next_cursor").Value);
                previousCursor = long.Parse(usersList.Element("previous_cursor").Value);
                // ReSharper restore PossibleNullReferenceException
            }

            return users;
        }

        /// <summary>
        /// Returns the members of the specified list.
        /// </summary>
        /// <param name="user">The owner of the list</param>
        /// <param name="list">The target list</param>
        /// <param name="cursor">Breaks the results into pages. This is recommended for users who are following many users. Provide a value of -1 to begin paging</param>
        /// <param name="previousCursor">Start index of the previous page</param>
        /// <param name="nextCursor">Start index of the next page</param>
        /// <returns>List of users</returns>
        /// <exception cref="ArgumentNullException"><paramref name="user" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><c>cursor</c> is out of range.</exception>
        public Collection<TwitterUser> GetListMembers(TwitterUser user, TwitterList list, long cursor, out long previousCursor,
                                                out long nextCursor)
        {
            if (user == null) throw new ArgumentNullException("user");
            if (list == null) throw new ArgumentNullException("list");
            if (cursor < -1) throw new ArgumentOutOfRangeException("cursor");

            return GetListMembers(user.ScreenName, list.Id, cursor, out previousCursor, out nextCursor);
        } 

        #endregion

        #region AddUserToList

        /// <summary>
        /// Adds a member to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="targetUserId">The ID of the user to add</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks><list type="bullet"><item><description>The authenticated user must own the list to be able to add members to it.</description></item><item><description>Lists are limited to having 500 members.</description></item></list></remarks>
        public TwitterList AddUserToList(string screenName, string listSlug, ulong targetUserId)
        {
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listSlug),
                                        false,
                                        new KeyValuePair<string, string>("id", targetUserId.ToString()));

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds a member to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <param name="targetUserId">The ID of the user to add</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it.</description></item>
        /// <item><description>Lists are limited to having 500 members.</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUserToList(string screenName, ulong listId, ulong targetUserId)
        {
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");
            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName,
                                                      listId),
                                        false,
                                        new KeyValuePair<string, string>("id", targetUserId.ToString()));

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds a member to a list.
        /// </summary>
        /// <param name="owner">The owner of the list</param>
        /// <param name="list">The target list</param>
        /// <param name="target">The user to add</param>
        /// <returns>Edited list</returns>
        /// <remarks><list type="bullet"><item><description>The authenticated user must own the list to be able to add members to it.</description></item><item><description>Lists are limited to having 500 members.</description></item></list></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="owner" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="target" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list" /> is <c>null</c>.</exception>
        public TwitterList AddUserToList(TwitterUser owner, TwitterList list, TwitterUser target)
        {
            if (owner == null) throw new ArgumentNullException("owner");
            if (target == null) throw new ArgumentNullException("target");
            if (list == null) throw new ArgumentNullException("list");

            return AddUserToList(owner.ScreenName, list.Id, target.UserId);
        }

        #endregion

        #region AddUsersToList

        /// <summary>
        /// Adds multiple members to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <param name="idsToAdd">List of user IDs (100 items ot most)</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, ulong listId, params long[] idsToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (idsToAdd == null || idsToAdd.Length == 0) throw new ArgumentNullException("idsToAdd");
            if (idsToAdd.Length > 100) throw new ArgumentOutOfRangeException("idsToAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();

            var value = string.Join(",", (from id in idsToAdd select id.ToString()).ToArray());
            keyvalues.Add(new KeyValuePair<string, string>("user_id", value));

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listId),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds multiple members to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list (100 items at most)</param>
        /// <param name="screenNamesToAdd">List of screen names</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, ulong listId, params string[] screenNamesToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (screenNamesToAdd == null || screenNamesToAdd.Length == 0) throw new ArgumentNullException("screenNamesToAdd");
            if (screenNamesToAdd.Length > 100) throw new ArgumentOutOfRangeException("screenNamesToAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();


            var value = string.Join(",", screenNamesToAdd);
            keyvalues.Add(new KeyValuePair<string, string>("screen_name", value));

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listId),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds multiple members to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="idsToAdd">List of user IDs (100 items at most)</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, string listSlug, params ulong[] idsToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");
            if (idsToAdd == null || idsToAdd.Length == 0) throw new ArgumentNullException("idsToAdd");
            if (idsToAdd.Length > 100) throw new ArgumentOutOfRangeException("idstoAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();

            var value = string.Join(",", (from id in idsToAdd select id.ToString()).ToArray());
            keyvalues.Add(new KeyValuePair<string, string>("user_id", value));

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listSlug),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds multiple members to a list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="screenNamesToAdd">List of screen names (100 items at most)</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, string listSlug, params string[] screenNamesToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");
            if (screenNamesToAdd == null || screenNamesToAdd.Length == 0) throw new ArgumentNullException("screenNamesToAdd");
            if (screenNamesToAdd.Length > 100) throw new ArgumentOutOfRangeException("screenNamesToAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();

            var value = string.Join(",", screenNamesToAdd);
            keyvalues.Add(new KeyValuePair<string, string>("screen_name", value));

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listSlug),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds multiple members to a list (100 items at a time).
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="idsToAdd">List of user IDs</param>
        /// <param name="screenNamesToAdd">List of screen names</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>Edited list</returns>
        /// <seealso cref="AddUsersToList(string,string,string[])"/>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, string listSlug, ulong[] idsToAdd,
                                            string[] screenNamesToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");
            if (screenNamesToAdd == null || screenNamesToAdd.Length == 0) throw new ArgumentNullException("screenNamesToAdd");
            if (screenNamesToAdd.Length > 100) throw new ArgumentOutOfRangeException("screenNamesToAdd");
            if (idsToAdd == null || idsToAdd.Length == 0) throw new ArgumentNullException("idsToAdd");
            if (idsToAdd.Length > 100) throw new ArgumentOutOfRangeException("idsToAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();

            var value = string.Join(",", (from id in idsToAdd select id.ToString()).ToArray());
            keyvalues.Add(new KeyValuePair<string, string>("user_id", value));

            value = string.Join(",", screenNamesToAdd);
            keyvalues.Add(new KeyValuePair<string, string>("screen_name", value));

            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listSlug),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        /// <summary>
        /// Adds multiple members to a list.
        /// </summary>
        /// <param name="owner">The owner of the list</param>
        /// <param name="list">Th target list</param>
        /// <param name="usersToAdd">List of users to add (at most 100 items)</param>
        /// <returns>Edited list</returns>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="owner" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Argument is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><c>usersToAdd</c> is out of range.</exception>
        public TwitterList AddUsersToList(TwitterUser owner, TwitterList list, params TwitterUser[] usersToAdd)
        {
            if (owner == null) throw new ArgumentNullException("owner");
            if (list == null) throw new ArgumentNullException("list");
            if (usersToAdd == null || usersToAdd.Length == 0) throw new ArgumentNullException("usersToAdd");
            if (usersToAdd.Length > 100) throw new ArgumentOutOfRangeException("usersToAdd");

            return AddUsersToList(owner.ScreenName, list.Slug, usersToAdd.Select(u => u.ScreenName).ToArray());
        }

        /// <summary>
        /// Adds multiple members to a list (100 items at a time).
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <param name="idsToAdd">List of user IDs</param>
        /// <param name="screenNamesToAdd">List of screen names</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>Edited list</returns>
        /// <seealso cref="AddUsersToList(string,string,string[])"/>
        /// <remarks>
        /// <list type="bullet">
        /// <item><description>The authenticated user must own the list to be able to add members to it</description></item>
        /// <item><description>Lists are limited to having 500 members</description></item>
        /// <item><description>This method can add 100 users at a time</description></item>
        /// </list>
        /// </remarks>
        public TwitterList AddUsersToList(string screenName, ulong listId, ulong[] idsToAdd, string[] screenNamesToAdd)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (screenNamesToAdd == null || screenNamesToAdd.Length == 0) throw new ArgumentNullException("screenNamesToAdd");
            if (screenNamesToAdd.Length > 100) throw new ArgumentOutOfRangeException("screenNamesToAdd");
            if (idsToAdd == null || idsToAdd.Length == 0) throw new ArgumentNullException("idsToAdd");
            if (idsToAdd.Length > 100) throw new ArgumentOutOfRangeException("idsToAdd");

            var keyvalues = new List<KeyValuePair<string, string>>();

            var value = string.Join(",", (from id in idsToAdd select id.ToString()).ToArray());
            keyvalues.Add(new KeyValuePair<string, string>("user_id", value));

            value = string.Join(",", screenNamesToAdd);
            keyvalues.Add(new KeyValuePair<string, string>("screen_name", value));


            var result = SendRequest(RequestMethod.Post,
                                        string.Format("https://api.twitter.com/1/{0}/{1}/members/create_all.xml",
                                                      screenName, listId),
                                        false,
                                        keyvalues.ToArray());

            var doc = XDocument.Parse(result);

            return ParseList(doc.Element("list"));
        }

        #endregion

        #region RemoveUserFromList

        /// <summary>
        /// Removes the specified member from the list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="targetUserId">The ID of the user to remove</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <remarks>The authenticated user must be the list's owner to remove members from the list.</remarks>
        public void RemoveUserFromList(string screenName, string listSlug, ulong targetUserId)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("listSlug");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");

            SendRequest(RequestMethod.Delete,
                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName, listSlug),
                        false,
                        new KeyValuePair<string, string>("id", targetUserId.ToString()));
        }

        /// <summary>
        /// Removes the specified member from the list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <param name="targetUserId">The ID of the user to remove</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <remarks>The authenticated user must be the list's owner to remove members from the list.</remarks>
        public void RemoveUserFromList(string screenName, ulong listId, ulong targetUserId)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");

            SendRequest(RequestMethod.Delete,
                        string.Format("https://api.twitter.com/1/{0}/{1}/members.xml", screenName, listId),
                        false,
                        new KeyValuePair<string, string>("id", targetUserId.ToString()));
        }

        /// <summary>
        /// Removes the specified member from the list.
        /// </summary>
        /// <param name="owner">The owner of the list</param>
        /// <param name="list">The target list</param>
        /// <param name="target">The user to remove from list</param>
        /// <remarks>The authenticated user must be the list's owner to remove members from the list.</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="owner" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="target" /> is <c>null</c>.</exception>
        public void RemoveUserFromList(TwitterUser owner, TwitterList list, TwitterUser target)
        {
            if (owner == null) throw new ArgumentNullException("owner");
            if (list == null) throw new ArgumentNullException("list");
            if (target == null) throw new ArgumentNullException("target");

            RemoveUserFromList(owner.ScreenName, list.Id, target.UserId);
        }

        #endregion

        #region IsUserMemberOfList

        /// <summary>
        /// Checks if a user is a member of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listSlug">The slug of the target list</param>
        /// <param name="targetUserId">The ID of the user to check</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>True if the user is a member of the list, otherwise false</returns>
        public bool IsUserMemberOfList(string screenName, string listSlug, ulong targetUserId)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (string.IsNullOrEmpty(listSlug)) throw new ArgumentNullException("screenName");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");

            try
            {
                SendRequest(RequestMethod.Get,
                            string.Format("https://api.twitter.com/1/{0}/{1}/members/{2}.xml", screenName, listSlug,
                                          targetUserId),
                            true);
            }
            catch (TwitterException ex)
            {
                if (ex.Message == "The specified user is not a member of this list")
                {
                    return false;
                }
                throw;
            }
            return true;
        }

        /// <summary>
        /// Checks if a user is a member of the specified list.
        /// </summary>
        /// <param name="screenName">Screen name of the owner of the list</param>
        /// <param name="listId">The ID of the target list</param>
        /// <param name="targetUserId">The ID of the user to check</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns>True if the user is a member of the list, otherwise false</returns>
        public bool IsUserMemberOfList(string screenName, ulong listId, ulong targetUserId)
        {
            if (string.IsNullOrEmpty(screenName)) throw new ArgumentNullException("screenName");
            if (listId < 1) throw new ArgumentOutOfRangeException("listId");
            if (targetUserId < 1) throw new ArgumentOutOfRangeException("targetUserId");

            try
            {
                SendRequest(RequestMethod.Get,
                            string.Format("https://api.twitter.com/1/{0}/{1}/members/{2}.xml", screenName, listId,
                                          targetUserId),
                            true);
            }
            catch (TwitterException ex)
            {
                if (ex.Message == "The specified user is not a member of this list")
                {
                    return false;
                }
                throw;
            }
            return true;
        }

        /// <summary>
        /// Checks if a user is a member of the specified list.
        /// </summary>
        /// <param name="owner">The owner of the list</param>
        /// <param name="list">The target list</param>
        /// <param name="target">The user to check for membership in given list</param>
        /// <returns>True if the user is a member of the list, otherwise false</returns>
        /// <exception cref="ArgumentNullException"><paramref name="owner" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="list" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="target" /> is <c>null</c>.</exception>
        public bool IsUserMemberOfList(TwitterUser owner, TwitterList list, TwitterUser target)
        {
            if (owner == null) throw new ArgumentNullException("owner");
            if (list == null) throw new ArgumentNullException("list");
            if (target == null) throw new ArgumentNullException("target");

            return IsUserMemberOfList(owner.ScreenName, list.Id, target.UserId);
        }

        #endregion

        #endregion
    }
}
